package com.coocaa.ops.admin.v1.upload.service.impl;

import com.coocaa.ops.admin.v1.upload.constant.ZipUploadTypeConstants;
import com.coocaa.ops.admin.v1.upload.enums.UploadCategoryEnums;
import com.coocaa.ops.admin.v1.upload.exception.FileCheckException;
import com.coocaa.ops.admin.v1.upload.model.*;
import com.coocaa.ops.admin.v1.upload.properties.UploadProperties;
import com.coocaa.ops.admin.v1.upload.service.IUploadService;
import com.coocaa.ops.admin.v1.upload.util.*;
import com.coocaa.ops.common.core.base.model.R;
import com.coocaa.ops.common.core.base.util.BeanCopyUtil;
import com.coocaa.ops.common.tool.base.InstanceUtil;
import com.coocaa.ops.common.tool.date.DateUtil;
import com.coocaa.ops.common.tool.math.RandomUtil;
import com.coocaa.ops.common.tool.string.PinyinUtil;
import com.coocaa.ops.common.tool.thread.NamedThreadFactory;
import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author tangminghong
 * @date 2020-06-18
 */
@Service
public class UploadServiceImpl implements IUploadService {
    
    @Autowired
    private UploadProperties uploadProperties;
    
    
    /**
     * 自定义线程池
     */
    private ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(
            5, 5, 0L, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue(),
            new NamedThreadFactory("upload-pool"),
            new ThreadPoolExecutor.CallerRunsPolicy());


    /**
     * 上传图片
     *
     * @param request
     * @return
     */
    @Override
    public Map<String, Object> uploadImage(HttpServletRequest request) {
        List<ImgUploadResult> data = UploadUtil.uploadImage(request);
        for (ImgUploadResult imgUploadResult : data) {
            //上传FTP
            handleImg2Ftp(imgUploadResult);
        }
        return R.ok(data);
    }

    /**
     * 上传zip
     *
     * @param request
     * @param uploadConfig
     * @return
     */
    @Override
    public Map<String, Object> uploadZip(HttpServletRequest request, UploadConfig uploadConfig) {
        List<UploadResult> data = UploadUtil.uploadTempFile(request, UploadCategoryEnums.ZIP);
        if (ZipUploadTypeConstants.NONE.equals(uploadConfig.getType())) {
            //TODO: zip2Ftp
            return R.ok(data);
        } else {
            List<ImgUploadResult> imgUploadResultList = handleUnZipIcon(data, uploadConfig.getType());
            return R.ok(imgUploadResultList);
        }
    }

    /**
     * 上传apk
     *
     * @param request
     * @return
     */
    @Override
    public Map<String, Object> uploadApk(HttpServletRequest request) {
        List<UploadResult> data = UploadUtil.uploadTempFile(request, UploadCategoryEnums.APK);
        //目前只有一个
        ApkUploadResult apkUploadResult = new ApkUploadResult();
        try {
            BeanCopyUtil.copyOrig2Target(data.get(0), apkUploadResult, "apk上传信息复制");
            String apkFilePath = apkUploadResult.getTempStorePath();
            //apk上传ftp
            handleApk2Ftp(apkFilePath, apkUploadResult);
            ApkInfoModel apkInfo = ApkAnalyzerUtil.getApkInfo(apkFilePath);
            String appFileMd5 = FileMd5Util.getFileMD5(apkFilePath);
            String appName = "";
            String appEngName = "";
            String icons = "";
            if (StringUtils.isNotBlank(apkInfo.getApplicationLabel())) {
                appName = apkInfo.getApplicationLabel();
                appEngName = PinyinUtil.getPingYin(apkInfo.getApplicationLabel());
            }
            if (StringUtils.isNotBlank(apkInfo.getIcons())) {
                //处理APK 图标ICONS
                ApkIconHandleUtil.handleApkIcons(apkInfo, apkFilePath);
                icons = apkInfo.getIcons();
                apkUploadResult.setAppIconUrl(UploadFilePathUtil.getFinalUrl(UploadCategoryEnums.IMG, icons));
            } else {
                apkUploadResult.setAppIconUrl("");
            }
            apkUploadResult.setAppName(appName);
            apkUploadResult.setAppEngName(appEngName);
            apkUploadResult.setAppVersionName(apkInfo.getVersionName() == null ? "" : apkInfo.getVersionName());
            apkUploadResult.setAppVersionNo(apkInfo.getVersion());
            apkUploadResult.setAppPackageName(apkInfo.getPackName());
            apkUploadResult.setAndroidVersion(apkInfo.getSdkversion());
            apkUploadResult.setAppIcon(icons);
            apkUploadResult.setFileMd5(appFileMd5);
        } finally {
            delTempFile(apkUploadResult.getTempStorePath());
            //置空临时上传目录
            apkUploadResult.setTempStorePath(null);
        }
        return R.ok().data(apkUploadResult);
    }

    /*************** ===私有方法=== ********************* ===start=== ***************************************/

    /**
     * apk 上传FTP
     *
     * @param apkFilePath
     * @param apkUploadResult
     */
    private void handleApk2Ftp(final String apkFilePath, ApkUploadResult apkUploadResult) {
        final String apkRemotePath = UploadFilePathUtil.getRemoteFilePathForApk(apkUploadResult.getNewFileName());
        //apk较大，开启线程专门处理
        poolExecutor.execute(new Runnable() {
            @Override
            public void run() {
                UploadUtil.upload2Ftp(apkFilePath, apkRemotePath);
            }
        });
        //获取最终的url
        apkUploadResult.setUrl(UploadFilePathUtil.getFinalUrl(UploadCategoryEnums.APK, apkRemotePath));
    }

    /**
     * zip解压
     *
     * @param data
     * @param type
     * @return
     */
    private List<ImgUploadResult> handleUnZipIcon(List<UploadResult> data, String type) {
        UploadResult uploadResult = data.get(0);
        String unZipDir = UploadFilePathUtil.getUnZipDir(uploadResult.getOriginFileName());
        try {
            ZipFile zipFile = new ZipFile(uploadResult.getTempStorePath());
            zipFile.extractAll(unZipDir);
        } catch (ZipException e) {
            e.printStackTrace();
        } finally {
            delTempFile(uploadResult.getTempStorePath());
        }
        return handleUnzipIcon2Ftp(unZipDir, type);
    }

    /**
     * zip解压缩内容 上传FTP
     *
     * @param unZipDir
     * @param type
     * @return
     */
    private List<ImgUploadResult> handleUnzipIcon2Ftp(String unZipDir, String type) {
        File imgDir = new File(unZipDir);
        List<ImgUploadResult> imgUploadResultList = InstanceUtil.newArrayList();
        //目标文件夹是否为空
        try {
            if (imgDir.isDirectory()) {
                File[] baseDirectory = imgDir.listFiles();
                if (baseDirectory == null || baseDirectory.length <= 0) {
                    throw new FileCheckException("压缩文件中数据为空!");
                }
                File[] themeIcons = null;
                //获取第目标文件夹中的文件夹中的所有文件
                for (File fileFilter : baseDirectory) {
                    if (fileFilter.getName().toUpperCase().equals(UploadFilePathUtil.DIR_MACOSX)) {
                        continue;
                    } else if (fileFilter.isDirectory()) {
                        themeIcons = fileFilter.listFiles();
                    }
                }
                String rootDir = getRootDirForThemeIcon();
                for (File file : themeIcons) {
                    if (file.isDirectory() || file.getName().indexOf(".") < 1) {
                        continue;
                    }
                    String originFileName = file.getName();
                    String tempFielName = originFileName;
                    if (ZipUploadTypeConstants.TAB_BG.equals(type)) {
                        tempFielName = tempFielName.replace("_tabBg", "");
                    } else if (ZipUploadTypeConstants.ICON.equals(type)) {
                        //图标和角标是一起的(如果有角标的话)
                        type = tempFielName.contains(ZipUploadTypeConstants.CORNER) ? ZipUploadTypeConstants.CORNER : ZipUploadTypeConstants.ICON;
                    }
                    // 上传到FTP
                    String remoteFilePath = UploadFilePathUtil.getRemoteFilePathForImg(type, rootDir, tempFielName);
                    UploadUtil.upload2Ftp(file, remoteFilePath);
                    if (!tempFielName.contains("focus") && !tempFielName.contains("selected")) {
                        //不传递落焦和选中的图片信息
                        String extName = FileAnalyzerUtil.getFileExtName(tempFielName);
                        String newName = UploadFilePathUtil.getRemoteFilePathForImg(type, rootDir, tempFielName);
                        String resolution = ImageAnalyzerUtil.getImgResolution(extName, file);
                        String fileMd5 = FileMd5Util.getFileMD5(file);
                        ImgUploadResult result = new ImgUploadResult();
                        result.setNewFileName(newName);
                        result.setOriginFileName(originFileName);
                        result.setFileType(extName);
                        result.setFileMd5(fileMd5);
                        result.setResolution(resolution);
                        //获取最终的url
                        result.setUrl(UploadFilePathUtil.getFinalUrl(UploadCategoryEnums.IMG, remoteFilePath));
                        imgUploadResultList.add(result);
                    }
                }
            }
        } finally {
            delTempDir(imgDir);
        }
        return imgUploadResultList;
    }

    /**
     * 图片 上传FTP
     *
     * @param imgUploadResult
     */
    private void handleImg2Ftp(ImgUploadResult imgUploadResult) {
        try {
            String remoteFilePath = UploadFilePathUtil.getRemoteFilePathForImg(imgUploadResult.getNewFileName());
            //上传FTP
            UploadUtil.upload2Ftp(imgUploadResult.getTempStorePath(), remoteFilePath);
            //获取最终的url
            imgUploadResult.setUrl(UploadFilePathUtil.getFinalUrl(UploadCategoryEnums.IMG, remoteFilePath));
        } finally {
            delTempFile(imgUploadResult.getTempStorePath());
            //置空临时上传目录
            imgUploadResult.setTempStorePath(null);
        }
    }

    /**
     * 获取主题目录的上传目录
     *
     * @return
     */
    private String getRootDirForThemeIcon() {
        StringBuilder path = new StringBuilder();
        path.append(DateUtil.getCurrentDateStr("yyyyMMdd"))
                .append("/")
                .append(RandomUtil.getRandomLongStr());
        return path.toString();
    }

    /**
     * 删除临时文件
     *
     * @param tempStorePath
     */
    private void delTempFile(String tempStorePath) {
        if (uploadProperties.getEnableUploadFtp()) {
            FileUtils.deleteQuietly(new File(tempStorePath));
        }
    }

    /**
     * 删除临时目录
     *
     * @param tempDirFile
     */
    private void delTempDir(File tempDirFile) {
        if (uploadProperties.getEnableUploadFtp()) {
            try {
                FileUtils.deleteDirectory(tempDirFile);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


}
